package com.meelive.ingkee.push;

import static com.meelive.ingkee.push.model.Constance.TAG;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.util.Log;

import com.meelive.ingkee.push.common.PushUtils;
import com.meelive.ingkee.push.model.InkePushType;
import com.meelive.ingkee.push.model.ReceiverInfo;
import com.meelive.ingkee.push.model.ReceiverType;
import com.meelive.ingkee.push.platform.IPush;
import com.meelive.ingkee.push.platform.hms.InkeHMSPush;
import com.meelive.ingkee.push.platform.jpush.InkeJPush;
import com.meelive.ingkee.push.platform.meizu.InkeMzPush;
import com.meelive.ingkee.push.platform.oppo.InkeOppoPush;
import com.meelive.ingkee.push.platform.vivo.InkeVivoPush;
import com.meelive.ingkee.push.platform.vivo.VIVOPushDispatcher;
import com.meelive.ingkee.push.platform.xiaomi.InkeMiPush;

import java.util.ArrayList;

/**
 * Create by: fanfeiyue
 * on: 2019-08-22
 * desc:
 */
public class InkePushHelper {

    private Context context;
    private InkePushConfig pushConfig;
    private IPush pushClient;
    private IPush jPushClient;

    private InkePushType pushType;
    private String pushToken;
    private String jPushToken;

    private boolean isClientInit = false;
    private boolean isJClientInit = false;

    private InkePushHelper() {
    }

    private static class InstanceHolder {
        static InkePushHelper INSTANCE = new InkePushHelper();
    }

    public static InkePushHelper getInstance() {
        return InstanceHolder.INSTANCE;
    }

    public void init(Context context, InkePushConfig config) {
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper init, config: " + config.toString());
        }

        if (context == null || config == null) {
            Log.d(TAG, "InkePushHelper init fail, Null parameters, context=" + context + ", config=" + config);
            return;
        }

        this.context = context.getApplicationContext();
        this.pushConfig = config;
        register();
    }

    private void register() {
        if (context == null || pushConfig == null) {
            Log.e(TAG, "InkePushHelper init(Context, InkePushConfig) method not call previously.");
            return;
        }
        if (isEnableJPush(pushConfig)) {
            register(InkePushType.JPUSH);
        }
        InkePushType pushType = getPreferPushType(pushConfig);
        if (pushType == null) {
            if (PushUtils.DEBUG) {
                Log.i(TAG, "InkePushHelper device is not support push: mi、huawei、meizu、oppo、vivo");
            }
            return;
        }
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper register, prefer push type: " + pushType);
        }
        register(pushType);
    }

    public void unregister(boolean unbindToken) {
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper unregister, unbind token: " + unbindToken);
        }

        if (!isClientInit) {
            Log.e(TAG, "InkePushHelper is not registered previously, return true directly.");
            return;
        }

        this.isClientInit = false;
        pushClient.unregister(context, pushConfig);
        unregisterJPush();

        if (!unbindToken) {
            pushType = null;
            return;
        }
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper Push type after unregister is " + pushType);
        }
    }

    public void unregisterJPush() {
        if (!isJClientInit) {
            Log.e(TAG, "InkePushHelper  is not registered JPush previously, return true directly.");
            return;
        }

        this.isJClientInit = false;
        jPushClient.unregister(context, pushConfig);
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper Push type after unregister is JPush");
        }
    }

    private void register(InkePushType pushType) {
        if (this.pushType == pushType) {
            Log.e(TAG, "InkePushHelper Push type " + pushType + " no change, return. ");
            return;
        }

        if (this.pushClient != null) {
            Log.e(TAG, pushClient.getPushType() + "InkePushHelper push already exists, unregister it and change to " + pushType + " push.");
            pushClient.unregister(context, pushConfig);
        }
        if (pushType != InkePushType.JPUSH) {
            this.pushType = pushType;
        }

        switch (pushType) {
            case MIPUSH:
                pushClient = new InkeMiPush();
                break;
            case OPPOPUSH:
                pushClient = new InkeOppoPush();
                break;
            case VIVOPUSH:
                pushClient = new InkeVivoPush();
                break;
            case MEIZUPUSH:
                pushClient = new InkeMzPush();
                break;
            case HMSPUSH:
                pushClient = new InkeHMSPush();
                break;
            case JPUSH:
                jPushClient = new InkeJPush();
                break;
        }

        if (pushClient != null) {
            this.isClientInit = true;
            pushClient.register(context, pushConfig);
        }
        if (jPushClient != null) {
            this.isJClientInit = true;
            jPushClient.register(context, pushConfig);
        }
    }

    public void onReceiveToken(InkePushType type, final String token) {
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper onReceiveToken: " + type + " - " + token);
        }
        if (type == InkePushType.JPUSH) {
            this.jPushToken = token;
        } else {
            this.pushToken = token;
        }
        ReceiverInfo info = new ReceiverInfo(type);
        info.token = token;
        PushUtils.sendBroadcast(context, ReceiverType.RECEIVER_TOKEN, info);
    }

    public void onErrorResponse(InkePushType type, long resultCode, String resultMsg) {
        Log.e(TAG, "InkePushHelper onErrorResponse: " + type + " - " + resultCode);
        if (!isClientInit) {
            Log.e(TAG, "InkePushHelper is not registered, abort error response action.");
            return;
        }
        ReceiverInfo info = new ReceiverInfo(type);
        info.errorCode = resultCode;
        info.message = resultMsg;
        PushUtils.sendBroadcast(context, ReceiverType.ERROR, info);
    }

    public void onPassThroughPush(Context context, String message, InkePushType pushType) {
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper [receiver passThrough message]，from：" + pushType + ", message：" + message);
        }
        ReceiverInfo info = new ReceiverInfo(pushType);
        info.message = message;
        PushUtils.sendBroadcast(context, ReceiverType.PASSTHROUGH, info);
    }

    public void onNotificationClick(Context context, String message, InkePushType pushType) {
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper [receiver notify click message]，from：" + pushType + ", message：" + message);
        }
        ReceiverInfo info = new ReceiverInfo(pushType);
        info.message = message;
        PushUtils.sendBroadcast(context, ReceiverType.NOTIFY_CLICK, info);
    }

    public void onNotificationArrived(Context context, String message, InkePushType pushType) {
        if (PushUtils.DEBUG) {
            Log.d(TAG, "InkePushHelper [receiver notify arrived message]，from：" + pushType + ", message：" + message);
        }
        ReceiverInfo info = new ReceiverInfo(pushType);
        info.message = message;
        PushUtils.sendBroadcast(context, ReceiverType.NOTIFY_ARRIVED, info);
    }

    private InkePushType getPreferPushType(InkePushConfig pushConfig) {
        InkePushType[] supportedPushTypes = new InkePushType[]{
                InkePushType.MIPUSH,
                InkePushType.HMSPUSH,
                InkePushType.MEIZUPUSH,
                InkePushType.OPPOPUSH,
                InkePushType.VIVOPUSH,
        };

        ArrayList<InkePushType> enabledPushTypes = pushConfig.getEnabledPushTypes();

        for (InkePushType pushType : supportedPushTypes) {
            if (enabledPushTypes.contains(pushType) && PushUtils.isSupportPush(pushType, pushConfig)) {
                return pushType;
            }
        }
        return null;
    }

    private boolean isEnableJPush(InkePushConfig pushConfig) {

        ArrayList<InkePushType> enabledPushTypes = pushConfig.getEnabledPushTypes();

        return enabledPushTypes.contains(InkePushType.JPUSH);
    }

//    private boolean isSupportPush(InkePushType pushType, InkePushConfig pushConfig) {
//        boolean support;
//        if (pushListener != null) {
//            support = pushListener.isSupportPush(pushType, pushConfig);
//        } else {
//            support = PushUtils.isSupportPush(pushType, pushConfig);
//        }
//        if (PushUtils.DEBUG) {
//            Log.d(TAG, "InkePushHelper isSupportPush: " + pushType + " - " + support);
//        }
//        return support;
//    }

    public InkePushType getPushType() {
        return pushType;
    }

    public String getPushToken() {
        return pushToken;
    }

    public String getJPushToken() {
        return jPushToken;
    }

    public InkePushConfig getPushConfig() {
        return pushConfig;
    }
}
